package org.covalence.core;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

public class Strings {
	
	/**
	 * @param string
	 * @param propertyName
	 * @return
	 */
	public static String propertyToAccessor(String string, String propertyName) {
		return string + propertyName.substring(0, 1).toUpperCase() + 
			propertyName.substring(1);		
	}
	
	/**
	 * @param accessor
	 * @return
	 */
	public static String accessorToProperty(String accessor) {
		return accessor.substring(3, 4).toLowerCase() + accessor.substring(4);
	}
	
	public static String descriptorToClassname(String descriptor) {
		if (descriptor.indexOf(';') > -1) {
			descriptor = descriptor.substring(1, descriptor.length() - 1);
		}
		return descriptor;
	}
	
	/**
	 * Convert an int opcode into the textual representation of the opcode
	 * @param c
	 * @return
	 */
	public static String opcode(int c) {
		switch (c) 
		{
		case Opcodes.NOP:
			return "NOP";
		case Opcodes.ACONST_NULL:
			return "ACONST_NULL";
		case Opcodes.ICONST_M1:
			return "ICONST_M1";
		case Opcodes.ICONST_0:
			return "ICONST_0";
		case Opcodes.ICONST_1:
			return "ICONST_1";
		case Opcodes.ICONST_2:
			return "ICONST_2";
	    case Opcodes.ICONST_3:
	    	return "ICONST_3";
	    case Opcodes.ICONST_4:
	    	return "ICONST_4";
	    case Opcodes.ICONST_5:
	    	return "ICONST_5";
	    case Opcodes.LCONST_0:
	    	return "LCONST_0";
	    case Opcodes.LCONST_1:
	    	return "LCONST_1";
	    case Opcodes.FCONST_0:
	    	return "FCONST_0";
	    case Opcodes.FCONST_1:
	    	return "FCONST_1";
	    case Opcodes.FCONST_2:
	    	return "FCONST_2";
	    case Opcodes.DCONST_0:
	    	return "DCONST_0";
	    case Opcodes.DCONST_1:
	    	return "DCONST_1";
	    case Opcodes.BIPUSH:
	    	return "BIPUSH";
	    case Opcodes.SIPUSH:
	    	return "SIPUSH";
	    case Opcodes.LDC:
	    	return "LDC";
		case Opcodes.ILOAD:
			return "ILOAD";
		case Opcodes.LLOAD:
			return "LLOAD";
		case Opcodes.FLOAD:
			return "FLOAD";
		case Opcodes.DLOAD:
			return "DLOAD";
		case Opcodes.ALOAD:
			return "ALOAD";
		case Opcodes.IALOAD:
			return "IALOAD";
	    case Opcodes.LALOAD:
	    	return "LALOAD";
	    case Opcodes.FALOAD:
	    	return "FALOAD";
	    case Opcodes.DALOAD:
	    	return "DALOAD";
	    case Opcodes.AALOAD:
	    	return "AALOAD";
	    case Opcodes.BALOAD:
	    	return "BALOAD";
	    case Opcodes.CALOAD:
	    	return "CALOAD";
	    case Opcodes.SALOAD:
	    	return "SALOAD";
	    case Opcodes.ISTORE:
	    	return "ISTORE";
	    case Opcodes.LSTORE:
	    	return "LSTORE";
	    case Opcodes.FSTORE:
	    	return "FSTORE";
	    case Opcodes.DSTORE:
	    	return "DSTORE";
	    case Opcodes.ASTORE:
	    	return "ASTORE";
	    case Opcodes.IASTORE:
	    	return "IASTORE";
	    case Opcodes.LASTORE:
	    	return "LASTORE";
	    case Opcodes.FASTORE:
	    	return "FASTORE";
	    case Opcodes.DASTORE:
	    	return "DASTORE";
	    case Opcodes.AASTORE:
	    	return "AASTORE";
	    case Opcodes.BASTORE:
	    	return "BASTORE";
	    case Opcodes.CASTORE:
	    	return "CASTORE";
	    case Opcodes.SASTORE:
	    	return "SASTORE";
	    case Opcodes.POP:
	    	return "POP";
	    case Opcodes.POP2:
	    	return "POP2";
	    case Opcodes.DUP:
	    	return "DUP";
	    case Opcodes.DUP_X1:
	    	return "DUP_X1";
	    case Opcodes.DUP_X2:
	    	return "DUP_X2";
	    case Opcodes.DUP2:
	    	return "DUP2";
	    case Opcodes.DUP2_X1:
	    	return "DUP2_X1";
	    case Opcodes.DUP2_X2:
	    	return "DUP2_X2";
	    case Opcodes.SWAP:
	    	return "SWAP";
	    case Opcodes.IADD:
	    	return "IADD";
	    case Opcodes.LADD:
	    	return "LADD";
	    case Opcodes.FADD:
	    	return "FADD";
	    case Opcodes.DADD:
	    	return "DADD";
	    case Opcodes.ISUB:
	    	return "ISUB";
	    case Opcodes.LSUB:
	    	return "LSUB";
	    case Opcodes.FSUB:
	    	return "FSUB";
	    case Opcodes.DSUB:
	    	return "DSUB";
	    case Opcodes.IMUL:
	    	return "IMUL";
	    case Opcodes.LMUL:
	    case Opcodes.FMUL:
	    case Opcodes.DMUL:
	    case Opcodes.IDIV:
	    case Opcodes.LDIV:
	    case Opcodes.FDIV:
	    case Opcodes.DDIV:
	    case Opcodes.IREM:
	    case Opcodes.LREM:
	    case Opcodes.FREM:
	    case Opcodes.DREM:
	    case Opcodes.INEG:
	    case Opcodes.LNEG:
	    case Opcodes.FNEG:
	    case Opcodes.DNEG:
	    case Opcodes.ISHL:
	    case Opcodes.LSHL:
	    case Opcodes.ISHR:
	    case Opcodes.LSHR:
	    case Opcodes.IUSHR:
	    case Opcodes.LUSHR:
	    case Opcodes.IAND:
	    case Opcodes.LAND:
	    case Opcodes.IOR:
	    case Opcodes.LOR:
	    case Opcodes.IXOR:
	    case Opcodes.LXOR:
	    case Opcodes.IINC:
	    case Opcodes.I2L:
	    case Opcodes.I2F:
	    case Opcodes.I2D:
	    case Opcodes.L2I:
	    case Opcodes.L2F:
	    case Opcodes.L2D:
	    case Opcodes.F2I:
	    case Opcodes.F2L:
	    case Opcodes.F2D:
	    case Opcodes.D2I:
	    case Opcodes.D2L:
	    case Opcodes.D2F:
	    case Opcodes.I2B:
	    case Opcodes.I2C:
	    case Opcodes.I2S:
	    case Opcodes.LCMP:
	    case Opcodes.FCMPL:
	    case Opcodes.FCMPG:
	    case Opcodes.DCMPL:
	    case Opcodes.DCMPG:
	    case Opcodes.IFEQ:
	    case Opcodes.IFNE:
	    case Opcodes.IFLT:
	    case Opcodes.IFGE:
	    case Opcodes.IFGT:
	    case Opcodes.IFLE:
	    case Opcodes.IF_ICMPEQ:
	    case Opcodes.IF_ICMPNE:
	    case Opcodes.IF_ICMPLT:
	    case Opcodes.IF_ICMPGE:
	    case Opcodes.IF_ICMPGT:
	    case Opcodes.IF_ICMPLE:
	    case Opcodes.IF_ACMPEQ:
	    case Opcodes.IF_ACMPNE:
	    case Opcodes.GOTO:
	    	return "GOTO";
	    case Opcodes.JSR:
	    case Opcodes.RET:
	    	return "RET";
	    case Opcodes.TABLESWITCH:
	    case Opcodes.LOOKUPSWITCH:
	    case Opcodes.IRETURN:
	    case Opcodes.LRETURN:
	    case Opcodes.FRETURN:
	    case Opcodes.DRETURN:
	    case Opcodes.ARETURN:
	    case Opcodes.RETURN:
	    	return "RETURN";
	    case Opcodes.GETSTATIC:
	    case Opcodes.PUTSTATIC:
	    case Opcodes.GETFIELD:
	    	return "GETFIELD";
	    case Opcodes.PUTFIELD:
	    	return "PUTFIELD";
	    case Opcodes.INVOKEVIRTUAL:
	    	return "INVOKEVIRTUAL";
	    case Opcodes.INVOKESPECIAL:
	    	return "INVOKESPECIAL";
	    case Opcodes.INVOKESTATIC:
	    	return "INVOKESTATIC";
	    case Opcodes.INVOKEINTERFACE:
	    	return "INVOKEINTERFACE";
	    // case Opcodes.UNUSED = 186; // NOT VISITED
	    case Opcodes.NEW:
	    	return "NEW";
	    case Opcodes.NEWARRAY:
	    case Opcodes.ANEWARRAY:
	    case Opcodes.ARRAYLENGTH:
	    case Opcodes.ATHROW:
	    case Opcodes.CHECKCAST:
	    case Opcodes.INSTANCEOF:
	    	return "INSTANCEOF";
	    case Opcodes.MONITORENTER:
	    case Opcodes.MONITOREXIT:
	    // case Opcodes.WIDE = 196; // NOT VISITED
	    case Opcodes.MULTIANEWARRAY:
	    case Opcodes.IFNULL:
	    	return "IFNULL";
	    case Opcodes.IFNONNULL:
	    	return "IFNONNULL";
		default:
			return "UNKNOWN";
		}
	}

	public static String access(int access) {
		StringBuffer sb = new StringBuffer();
		if ((access & Opcodes.ACC_PUBLIC) != 0) {
			sb.append("ACC_PUBLIC");
		}
		if ((access & Opcodes.ACC_PRIVATE) != 0) {
			sb.append("ACC_PRIVATE");
		}
		
		return sb.toString();
	}

	public static String calcFMCSig(int sort) {
		switch (sort) {
			case Type.BOOLEAN:
				return "(Ljava/lang/String;ZZ)V";
			case Type.INT:
				return "(Ljava/lang/String;II)V";
			case Type.CHAR:
				return "(Ljava/lang/String;II)V";
			case Type.BYTE:
				return "(Ljava/lang/String;II)V";
			case Type.SHORT:
				return "(Ljava/lang/String;II)V";
			case Type.LONG:
				return "(Ljava/lang/String;JJ)V";
			case Type.DOUBLE:
				return "(Ljava/lang/String;DD)V";
			case Type.FLOAT:
				return "(Ljava/lang/String;FF)V";
			default:
				return "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V";
		}	
	}
}
